解決 WSL 2 Docker 檔案權限問題
TLDR
- 核心問題:WSL 2 環境中,Docker 容器以
root權限建立的檔案,會導致一般使用者身分的 VS Code 無法讀寫,出現Permission Denied。 - 暴力解法(不推薦):修改
/etc/wsl.conf將 WSL 預設使用者改為root,雖能解決權限問題,但存在極大資安風險。 - 推薦做法 (Dev Containers):使用 VS Code 的 Dev Containers 功能,將開發環境容器化,並透過
"remoteUser": "root"設定解決 Bind Mount 的權限衝突。 - 進階做法 (整合進 Docker Compose):在
compose.yml中定義一個vscode-editor服務,並透過Dev Containers: Attach to Running Container連線,將開發環境與專案基礎設施整合。 - 關鍵提示:使用
docker-outside-of-docker時,若使用 Bind Mount,路徑解析會指向 Host,建議優先考慮使用 Named Volume 以避開路徑對應問題。
遇到的權限地獄
什麼情況下會遇到這個問題:當你在 WSL 2 中使用 Docker Compose 啟動容器,且容器將檔案掛載(Volume)至本機目錄時。
由於 Docker 容器預設以 root 權限執行,掛載至 WSL 的檔案擁有者會變為 root。當你使用以一般使用者身分執行的 VS Code 嘗試編輯這些檔案時,會因權限不足而失敗。
暴力解法
直接修改 WSL 的設定檔 /etc/wsl.conf,將預設登入使用者改為 root。
ini
# /etc/wsl.conf
[user]
default = rootWARNING
這是一個極度不安全的作法。將預設使用者改為 root 會讓你在 WSL 內的所有操作都具有最高權限,一旦誤執行惡意腳本或操作失誤(例如 rm -rf /),後果不堪設想。請勿在生產環境或重要的工作環境中模仿。
解決方案:Dev Containers
什麼情況下會遇到這個問題:當你希望在保持環境一致性的同時,解決跨作業系統的檔案存取權限問題。
Dev Containers 允許將開發環境打包在容器中,並透過自動同步 UID 或指定 remoteUser 來解決權限衝突。
Dev Containers 實戰步驟
- 初始化:在 VS Code 中按下
F1,選擇 Dev Containers: Add Dev Container Configuration Files...。 - 選擇定義:選擇適合的環境(如
Ubuntu),並務必勾選Docker (outside of Docker)功能。 - 設定
devcontainer.json: 若使用 Bind Mount,必須在設定檔中啟用remoteUser:json"remoteUser": "root" - 重新開啟:按下
F1選擇 Dev Containers: Reopen in Container。
TIP
devcontainer.json 若有修改,必須執行 Rebuild 才會生效。若錯過重建提示,可透過指令面板重新執行。
進階做法:將 Dev Container 整合進 Docker Compose
什麼情況下會遇到這個問題:當你不希望產生額外的 .devcontainer 資料夾,或希望開發環境與專案服務定義在同一個 compose.yml 中。
你可以新增一個專門用於編輯的容器服務:
設定方式
在 compose.yml 或 compose.override.yml 中加入:
yaml
services:
vscode-editor:
image: mcr.microsoft.com/devcontainers/base:ubuntu-24.04
container_name: vscode-editor
command: sleep infinity
user: root
volumes:
- ./:/workspace
working_dir: /workspace連結步驟
- 啟動服務:
docker compose up -d。 - 在 VS Code 中按下
F1,選擇 Dev Containers: Attach to Running Container...。 - 選擇
vscode-editor容器。 - 開啟容器內的
/workspace目錄。
TIP
若不希望開發環境設定汙染正式的 compose.yml,建議將上述設定移至 compose.override.yml,Docker Compose 會自動合併設定。
異動歷程
- 初版文件建立。
- 補充將 Dev Container 整合進 Docker Compose 的另一種做法。
- 補充關於使用 compose.override.yml 的建議。